import * as chai from "chai";
import * as chaiProperties from 'chai-properties'
import * as request from 'supertest'
import {InstanceType} from "typegoose"
import * as  xml2js from 'xml2js'
import {jwtSign} from "../../api/jwt";
import {mkCdKeys} from "../../api/utils";
import {Address, AddressModel} from "../../database/models/address";
import {Cdkey, CdkeyModel} from "../../database/models/cdkey";
import {CdkeyRecordModel} from "../../database/models/cdkeyRecord";
import {ConsumeRecordModel} from "../../database/models/consumeRecord";
import {DeliveryModel} from "../../database/models/delivery";
import {DeliveryOrderModel} from "../../database/models/deliveryOrder";
import {GameActivityModel} from "../../database/models/gameActivity";
import {GamePrizeModel} from "../../database/models/gamePrize";
import GM from "../../database/models/gm";
import {KickbackRecordModel} from "../../database/models/kickbackRecord";
import {LipstickGameOrderModel} from "../../database/models/lipstickGameOrder";
import {
  LipstickSeries,
  LipstickSeriesModel,
  PlayerSeriesIncomeModel,
  SeriesIncomeModel
} from "../../database/models/lipstickSeries";
import {Mail, MailModel, PublicMail, PublicMailModel, PublicMailRecordModel} from "../../database/models/mail";
import {PaymentOrderModel} from "../../database/models/paymentOrder";
import {Player, PlayerModel} from "../../database/models/player";
import {PressGameOrderModel} from "../../database/models/pressGameOrder";
import {Product, ProductModel} from "../../database/models/Product";
import {
  PressGroup,
  PressGroupIncomeModel,
  PressGroupModel,
  ProductGroup,
  ProductGroupModel
} from "../../database/models/ProductGroup";
import {ProductOrderModel} from "../../database/models/ProductOrder";
import {Recharge, RechargeModel} from "../../database/models/recharge";
import {RechargeOrderModel} from "../../database/models/rechargeOrder";
import AdvisementModel from "../../database/models/advisement";
import {SeriesIncomeThresholdModel} from "../../database/models/seriesIncomeThreshold";
import app from "../../serverApp";
import {
  testCdkey,
  testLipstickSeries,
  testLittleGift,
  testPointMarketProduct,
  testPressGroup,
  testProduct,
  testRecharge
} from "../initData/data";

chai.use(chaiProperties)

export const {expect} = chai

export function requestToApiServer() {
  return request(app)
}

export type TestEnv = {
  player: InstanceType<Player>, playerPoor: InstanceType<Player>, playerNoInvite: InstanceType<Player>,
  product: InstanceType<Product>,
  pointProduct: InstanceType<Product>,
  productGroup: InstanceType<ProductGroup>,
  luckyGroup: InstanceType<ProductGroup>,
  pressGroup: InstanceType<PressGroup>, pressGroup221: InstanceType<PressGroup>,
  jwt: string, jwtPoor: string, jwtNoInvite: string,
  gift: InstanceType<Product>,
  recharge: InstanceType<Recharge>,
  address: InstanceType<Address>,
  lipstickSeries: InstanceType<LipstickSeries>,
  cdkeyOneToAll: InstanceType<Cdkey>, cdkeyOneToSome: InstanceType<Cdkey>, cdkeyAllToAll: InstanceType<Cdkey>
}

const randomString = () => `${Math.random().toFixed(10)}`

const randomProduct = p => ({...p, model: `chili_${randomString()}`, skuId: randomString(), stock: 26})
const randomLittleGift = () => ({...testLittleGift, model: `chili_${randomString()}`, skuId: randomString(), stock: 26})

export async function setupTestEnv() {
  const inviteCode = Date.now().toString().slice(-6)
  const gm = new GM({
    username: 't' + inviteCode,
    password: 't' + inviteCode,
    role: 'super',
    inviteCode
  })
  gm.relation = [gm]
  await gm.save()

  const gm1 = new GM({
    username: 't1' + inviteCode,
    password: 't1' + inviteCode,
    role: 'level1',
    superior: gm,
    inviteCode: (inviteCode + 1).toString(),
  })
  gm1.relation = [gm1, gm]
  await gm1.save()

  const gm2 = new GM({
    username: 't2' + inviteCode,
    password: 't2' + inviteCode,
    role: 'level2',
    inviteCode: (inviteCode + 2).toString(),
    superior: gm1,
  })
  gm2.relation = [gm2, gm1, gm]
  await gm2.save()

  const player = await PlayerModel.create({
    name: 'reporter',
    shortId: 99999,
    coin: 100000,
    freeCoin: 150,
    gem: 1000,
    cookie: 'cookie',
    sex: 0,
    inviteBy: gm2
  })

  const playerNoInvite = await PlayerModel.create({
    name: 'reporter',
    shortId: 99999,
    coin: 100000,
    freeCoin: 150,
    gem: 1000,
    cookie: 'cookie',
    sex: 0,
  })

  const playerPoor = await PlayerModel.create({
    name: 'reporterPoor',
    shortId: 66666,
    coin: 0,
    freeCoin: 0,
    gem: 0,
    cookie: 'cookie',
    sex: 0
  })
  const product = await ProductModel.create(testProduct)

  const product1 = await ProductModel.create(randomProduct(testProduct))
  const product2 = await ProductModel.create(randomProduct(testProduct))
  const product3 = await ProductModel.create(randomProduct(testProduct))
  const product4 = await ProductModel.create(randomProduct(testProduct))
  const product5 = await ProductModel.create(randomProduct(testProduct))

  const pointProduct = await ProductModel.create(randomProduct(testPointMarketProduct))
  const pointProduct2 = await ProductModel.create(randomProduct(testPointMarketProduct))

  const gift = await ProductModel.create(randomLittleGift())
  const littleGift1 = await ProductModel.create(randomLittleGift())
  const littleGift2 = await ProductModel.create(randomLittleGift())
  const littleGift3 = await ProductModel.create(randomLittleGift())
  const littleGift4 = await ProductModel.create(randomLittleGift())

  const productGroup = await ProductGroupModel.create({
    name: 'test',
    description: "group描述test",
    priceInCoin: 0,
    priceInGem: 100,
    level1: [product1, gift, littleGift1, littleGift2],
    level2: [product2, littleGift3, littleGift4],
    level3: [product3, littleGift4],
    level4: [product4],
    state: 'on',
    category: `eggDraw`
  })

  const luckyGroup = await ProductGroupModel.create({
    name: 'test',
    description: "group描述test",
    priceInCoin: 0,
    priceInGem: 100,
    level1: [product1, gift, littleGift1, littleGift2],
    level2: [product2, littleGift3, littleGift4],
    level3: [product3, littleGift4],
    level4: [product4],
    state: 'on',
    category: `luckyBox`
  })

  const lipstickSeries = await LipstickSeriesModel.create({
    ...testLipstickSeries,
    products: [product, product1, product2],
    category: 'lipstick'
  })

  const lipstickSeries2 = await LipstickSeriesModel.create({
    ...testLipstickSeries,
    products: [product3, product4],
    category: 'lipstick'
  })

  const lipstickSeries3 = await LipstickSeriesModel.create({
    ...testLipstickSeries,
    products: [product, product1],
    category: 'lipstick'
  })

  const lipstickSeries4 = await LipstickSeriesModel.create({
    ...testLipstickSeries,
    products: [product2, product3],
    category: 'lipstick'
  })
  const lipstickSeries5 = await LipstickSeriesModel.create({
    ...testLipstickSeries,
    products: [product4, product5],
    category: 'lipstick'
  })

  const pressGroup = await PressGroupModel.create({
    ...testPressGroup,
    level1: [lipstickSeries3],
    level2: [lipstickSeries4],
    level3: [lipstickSeries5],
  })

  const pressGroup221 = await PressGroupModel.create({
    ...testPressGroup,
    level1: [lipstickSeries3, lipstickSeries4],
    level2: [lipstickSeries3, lipstickSeries4],
    level3: [lipstickSeries3],
  })

  const address = new AddressModel({
    pcasCode: '330109012',
    player,
    province: '浙江省', city: '杭州市', area: '萧山区', street: '闻堰街道',
    detail: 'here',
    phone: '13344445555',
    receiver: 'hello',
    default: true,
    createAt: new Date()
  })
  await address.save()

  const recharge = await RechargeModel.create(testRecharge)

  const jwt = jwtSign({
    _id: player.id, cookie: player.cookie
  })

  const jwtNoInvite = jwtSign({
    _id: playerNoInvite.id, cookie: playerNoInvite.cookie
  })

  const jwtPoor = jwtSign({
    _id: playerPoor.id, cookie: playerPoor.cookie
  })

  const cdkeyOneToAll = await CdkeyModel.create({
    name: '生蛋快乐活动兑换码',
    keys: ['hello world'],
    type: 'OneToAll',
    ...testCdkey
  })

  const cdkeyOneToSome = await CdkeyModel.create({
    name: 'UserPlayers专属兑换码',
    keys: ['hello'],
    type: 'OneToSome',
    toPlayers: [player.id],
    ...testCdkey
  })

  const cdkeyAllToAll = await CdkeyModel.create({
    name: '六一儿童节限量兑换码',
    keys: mkCdKeys(100),
    type: 'AllToAll',
    ...testCdkey
  })

  return {
    player, jwt, product, pointProduct, productGroup, luckyGroup, pressGroup, pressGroup221,
    gift, address, recharge, lipstickSeries, playerPoor, jwtPoor, playerNoInvite, jwtNoInvite,
    cdkeyOneToAll, cdkeyOneToSome, cdkeyAllToAll,
    gm, gm1, gm2
  }
}

export async function tearDownTestEnv() {
  await Promise.all([
    PlayerModel.deleteMany({}),
    ProductModel.deleteMany({}),
    GameActivityModel.deleteMany({}),
    AddressModel.deleteMany({}),
    SeriesIncomeModel.deleteMany({}),
    ProductGroupModel.deleteMany({}),
    ConsumeRecordModel.deleteMany({}),
    DeliveryModel.deleteMany({}),
    PlayerSeriesIncomeModel.deleteMany({}),
    SeriesIncomeThresholdModel.deleteMany({}),
    RechargeModel.deleteMany({}),
    PaymentOrderModel.deleteMany({}),
    ProductOrderModel.deleteMany({}),
    DeliveryOrderModel.deleteMany({}),
    LipstickGameOrderModel.deleteMany({}),
    RechargeOrderModel.deleteMany({}),
    AdvisementModel.deleteMany({}),
    LipstickSeriesModel.deleteMany({}),
    GamePrizeModel.deleteMany({}),
    PressGroupModel.deleteMany({}),
    PressGameOrderModel.deleteMany({}),
    PressGroupIncomeModel.deleteMany({}),
    PaymentOrderModel.deleteMany({}),
    GM.deleteMany({}),
    CdkeyModel.deleteMany({}),
    CdkeyRecordModel.deleteMany({}),
    MailModel.deleteMany({}),
    PublicMailModel.deleteMany({}),
    PublicMailRecordModel.deleteMany({}),
    KickbackRecordModel.deleteMany({})
  ])
}

export const addressCreateData = {
  pcas: '330108003',
  address: '保亿大厦2222室',
  receiver: 'pshu',
  phone: '18688887777',
  alias: '公司2',
  default: true
}

export const XMLbuilder = new xml2js.Builder({
  rootName: 'xml',
  headless: true
})
